#include <mosquitto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sqlite3.h>
#include <stdbool.h>
#include <curl/curl.h>
#include "cJSON.h"

// MQTT 配置
#define ID_MQTT  "d542e726e7594ade9022b7b9bf97c063"
const char* mqtt_server = "bemfa.com";
const int mqtt_server_port = 9501;
const char* dhttopic = "temp004";      // 温湿度主题
const char* dishes_topic = "dishs004"; // 菜品主题
const char* moldy_topic = "moldy004";   // 发霉/新鲜度主题
const char* led_control_topic = "led002"; // LED 控制主题
const char* image_upload_url = "http://images.bemfa.com/upload/v1/upimages.php"; // 图片上传URL

// 全局变量存储 LED 状态和上一次的状态
bool led_state = true;
bool last_led_state = true;

// 全局 MQTT 客户端实例
struct mosquitto *global_mosq = NULL;
bool mqtt_initialized = false;

// 结构体用于存储传感器数据
typedef struct {
    double temperature;
    double humidity;
    char freshness[6];        // 菜品状态（新鲜度）
    char recommended_dish[36]; // 推荐菜品
} SensorData;

// 声明辅助函数
int read_sensor_data(SensorData *data);
int upload_image(const char* file_path, const char* topic, char* url_buffer, size_t buffer_size);
void publish_partial_data(int x, bool led_state);
void publish_partial_data_helper(const SensorData *data, bool led_state);
void publish_full_data_helper(const SensorData *data, bool led_state);
void init_mqtt_client();
void cleanup_mqtt_client();
void start_mqtt_publisher(int x, bool led_state);
bool mqtt_receive();

// 回调函数定义
void on_connect(struct mosquitto *mosq, void *obj, int reason_code) {
    if (reason_code != MOSQ_ERR_SUCCESS) {
        fprintf(stderr, "Connection failed: %s\n", mosquitto_connack_string(reason_code));
        return;
    }

    // 订阅 LED 控制主题
    int rc = mosquitto_subscribe(mosq, NULL, led_control_topic, 1);
    if (rc != MOSQ_ERR_SUCCESS) {
        fprintf(stderr, "Subscription error: %s\n", mosquitto_strerror(rc));
    }
}

void on_publish(struct mosquitto *mosq, void *obj, int mid) {
    printf("Message published (mid: %d)\n", mid);
}

void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    if (strcmp(msg->topic, led_control_topic) == 0) {
        if (msg->payloadlen > 0 && msg->payload != NULL) {
            char payload[msg->payloadlen + 1];
            strncpy(payload, (char*)msg->payload, msg->payloadlen);
            payload[msg->payloadlen] = '\0';
            if (strcmp(payload, "on") == 0) {
                led_state = true;
            } else if (strcmp(payload, "off") == 0) {
                led_state = false;
            }
        }
    }
}

void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) {
    printf("Subscribed (mid: %d): ", mid);
    for (int i = 0; i < qos_count; i++) {
        printf("%d ", granted_qos[i]);
    }
    printf("\n");
}

// 从数据库中读取温湿度、菜品信息和状态
int read_sensor_data(SensorData *data) {
    sqlite3* db_aht20;
    sqlite3* db_menu;
    sqlite3* db_food;
    char* zErrMsg = 0;
    int rc;

    // 打开 aht20 数据库
    rc = sqlite3_open("/userdata/main/sqlite/aht20.db", &db_aht20);
    if (rc) {
        fprintf(stderr, "Database error: %s\n", sqlite3_errmsg(db_aht20));
        return rc;
    }

    // 查询最新温湿度数据
    const char* sql_aht20 = "SELECT temperature, humidity FROM aht20 ORDER BY time DESC LIMIT 1";
    sqlite3_stmt *stmt_aht20;
    rc = sqlite3_prepare_v2(db_aht20, sql_aht20, -1, &stmt_aht20, 0);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL prepare error: %s\n", sqlite3_errmsg(db_aht20));
        sqlite3_close(db_aht20);
        return rc;
    }

    // 执行查询
    rc = sqlite3_step(stmt_aht20);
    if (rc == SQLITE_ROW) {
        data->temperature = sqlite3_column_double(stmt_aht20, 0);
        data->humidity = sqlite3_column_double(stmt_aht20, 1);
    } else if (rc == SQLITE_DONE) {
        fprintf(stderr, "No data found in the aht20 database.\n");
        sqlite3_finalize(stmt_aht20);
        sqlite3_close(db_aht20);
        return SQLITE_ERROR;
    } else {
        fprintf(stderr, "SQL step error: %s\n", sqlite3_errmsg(db_aht20));
        sqlite3_finalize(stmt_aht20);
        sqlite3_close(db_aht20);
        return rc;
    }

    sqlite3_finalize(stmt_aht20);
    sqlite3_close(db_aht20);

    // 打开 menu 数据库
    rc = sqlite3_open("/userdata/main/sqlite/menu.db", &db_menu);
    if (rc) {
        fprintf(stderr, "Database error: %s\n", sqlite3_errmsg(db_menu));
        return rc;
    }

    // 查询最新品信息和状态
    const char* sql_menu = "SELECT freshness, recognition_result FROM menu ORDER BY time DESC LIMIT 1";
    sqlite3_stmt *stmt_menu;
    rc = sqlite3_prepare_v2(db_menu, sql_menu, -1, &stmt_menu, 0);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL prepare error: %s\n", sqlite3_errmsg(db_menu));
        sqlite3_close(db_menu);
        return rc;
    }

    // 执行查询
    rc = sqlite3_step(stmt_menu);
    if (rc == SQLITE_ROW) {
        strncpy(data->freshness, (const char*)sqlite3_column_text(stmt_menu, 0), sizeof(data->freshness) - 1);
        strncpy(data->recommended_dish, (const char*)sqlite3_column_text(stmt_menu, 1), sizeof(data->recommended_dish) - 1);

        // 确保字符串以null结尾
        data->freshness[sizeof(data->freshness) - 1] = '\0';
        data->recommended_dish[sizeof(data->recommended_dish) - 1] = '\0';
    } else if (rc == SQLITE_DONE) {
        fprintf(stderr, "No data found in the menu database.\n");
        sqlite3_finalize(stmt_menu);
        sqlite3_close(db_menu);
        return SQLITE_ERROR;
    } else {
        fprintf(stderr, "SQL step error: %s\n", sqlite3_errmsg(db_menu));
        sqlite3_finalize(stmt_menu);
        sqlite3_close(db_menu);
        return rc;
    }

    sqlite3_finalize(stmt_menu);
    sqlite3_close(db_menu);

    // 打开 food 数据库
    rc = sqlite3_open("/userdata/main/sqlite/food.db", &db_food);
    if (rc) {
        fprintf(stderr, "Database error: %s\n", sqlite3_errmsg(db_food));
        return rc;
    }

    // 查询推荐菜单结果
    const char* sql_food = "SELECT recommended_dish FROM food ORDER BY time DESC LIMIT 1";
    sqlite3_stmt *stmt_food;
    rc = sqlite3_prepare_v2(db_food, sql_food, -1, &stmt_food, 0);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL prepare error: %s\n", sqlite3_errmsg(db_food));
        sqlite3_close(db_food);
        return rc;
    }

    // 执行查询
    rc = sqlite3_step(stmt_food);
    if (rc == SQLITE_ROW) {
        strncpy(data->recommended_dish, (const char*)sqlite3_column_text(stmt_food, 0), sizeof(data->recommended_dish) - 1);
        // 确保字符串以null结尾
        data->recommended_dish[sizeof(data->recommended_dish) - 1] = '\0';
    } else if (rc == SQLITE_DONE) {
        fprintf(stderr, "No data found in the food database.\n");
        sqlite3_finalize(stmt_food);
        sqlite3_close(db_food);
        return SQLITE_ERROR;
    } else {
        fprintf(stderr, "SQL step error: %s\n", sqlite3_errmsg(db_food));
        sqlite3_finalize(stmt_food);
        sqlite3_close(db_food);
        return rc;
    }

    sqlite3_finalize(stmt_food);
    sqlite3_close(db_food);
    return SQLITE_OK;
}

// 定义 MemoryStruct 结构体
struct MemoryStruct {
    char *memory;
    size_t size;
};

// 回调函数用于接收服务器响应
size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;
    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if(ptr == NULL) {
        /* out of memory! */
        return 0;
    }
    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
    return realsize;
}

// 上传图片并获取URL
int upload_image(const char* file_path, const char* topic, char* url_buffer, size_t buffer_size) {
    CURL *curl;
    CURLcode res;
    struct MemoryStruct chunk;
    chunk.memory = malloc(1);  /* will be grown as needed by the realloc above */
    chunk.size = 0;    /* no data at this point */

    curl_global_init(CURL_GLOBAL_ALL);

    // 检查文件是否存在
    FILE *file = fopen(file_path, "rb"); // 以二进制模式打开文件
    if (!file) {
        perror("File not found or cannot be opened");
        free(chunk.memory);
        return 1;
    }

    // 获取文件大小
    fseek(file, 0L, SEEK_END);
    long file_size = ftell(file);
    rewind(file);

    // 分配内存以存储文件内容
    unsigned char *file_content = malloc(file_size);
    if (!file_content) {
        fprintf(stderr, "Not enough memory to allocate file content\n");
        fclose(file);
        free(chunk.memory);
        return 1;
    }

    // 读取文件内容
    size_t bytes_read = fread(file_content, 1, file_size, file);
    fclose(file);
    if (bytes_read != file_size) {
        fprintf(stderr, "Error reading file content\n");
        free(file_content);
        free(chunk.memory);
        return 1;
    }

    curl = curl_easy_init();
    if(curl) {
        struct curl_slist *headerlist = NULL;
        
        // 使用设备ID作为Authorization
        char auth_header[256];
        snprintf(auth_header, sizeof(auth_header), "Authorization: %s", ID_MQTT);
        headerlist = curl_slist_append(headerlist, auth_header);
        
        // 使用主题作为Authtopic
        char topic_header[256];
        snprintf(topic_header, sizeof(topic_header), "Authtopic: %s", topic);
        headerlist = curl_slist_append(headerlist, topic_header);
        
        // 设置正确的Content-Type
        headerlist = curl_slist_append(headerlist, "Content-Type: application/octet-stream");

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
        curl_easy_setopt(curl, CURLOPT_URL, image_upload_url);
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, file_content);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, file_size);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
            fprintf(stderr, "Upload failed: %s\n", curl_easy_strerror(res));
            free(chunk.memory);
            curl_easy_cleanup(curl);
            curl_slist_free_all(headerlist);
            free(file_content);
            return 1;
        }

        // 检查服务器返回的内容是否为 JSON
        cJSON *parsed_json;
        parsed_json = cJSON_Parse(chunk.memory);
        if (!parsed_json) {
            fprintf(stderr, "Received invalid JSON response\n");
            free(chunk.memory);
            curl_easy_cleanup(curl);
            curl_slist_free_all(headerlist);
            free(file_content);
            return 1;
        }

        cJSON *url_obj = cJSON_GetObjectItemCaseSensitive(parsed_json, "url");
        if (!cJSON_IsString(url_obj) || (url_obj->valuestring == NULL)) {
            fprintf(stderr, "No 'url' field in JSON response\n");
            cJSON_Delete(parsed_json);
            free(chunk.memory);
            curl_easy_cleanup(curl);
            curl_slist_free_all(headerlist);
            free(file_content);
            return 1;
        }

        snprintf(url_buffer, buffer_size, "%s", url_obj->valuestring);

        cJSON_Delete(parsed_json);
        free(chunk.memory);
        curl_easy_cleanup(curl);
        curl_slist_free_all(headerlist);
        free(file_content);
        return 0;
    }

    free(chunk.memory);
    curl_easy_cleanup(curl);
    free(file_content);
    return 1;
}

// 发布传感器数据到MQTT
void publish_partial_data(int x, bool led_state) {
    static SensorData last_sensor_data = {0.0, 0.0, "", ""};
    SensorData current_sensor_data = {0.0, 0.0, "", ""};
    char image_url[256] = "";

    // 从数据库中读取温湿度、菜品信息和状态
    int rc = read_sensor_data(&current_sensor_data);
    if (rc != SQLITE_OK || strlen(current_sensor_data.freshness) == 0 || strlen(current_sensor_data.recommended_dish) == 0) {
        fprintf(stderr, "Failed to read data from database or no data found.\n");
    } else {
        // 检查是否有任何数据变化
        if (x == 1 && strcmp(current_sensor_data.recommended_dish, last_sensor_data.recommended_dish) != 0) {
            // 上传图片并获取URL
            rc = upload_image("/userdata/main/img/food.jpg", "dishes", image_url, sizeof(image_url));
            if (rc != 0) {
                fprintf(stderr, "Failed to upload image.\n");
                // 即使上传失败，也要发布其他数据
                publish_partial_data_helper(&current_sensor_data, led_state);
            } else {
                printf("Image uploaded successfully. URL: %s\n", image_url);

                // 发布所有数据，不包括图片URL
                publish_full_data_helper(&current_sensor_data, led_state);
            }
        } else if ((x == 0 || x == 1) &&
                   (last_sensor_data.temperature != current_sensor_data.temperature ||
                    last_sensor_data.humidity != current_sensor_data.humidity ||
                    strcmp(last_sensor_data.freshness, current_sensor_data.freshness) != 0 ||
                    strcmp(last_sensor_data.recommended_dish, current_sensor_data.recommended_dish) != 0 ||
                    last_led_state != led_state)) {
            // 仅发布部分数据
            publish_partial_data_helper(&current_sensor_data, led_state);
        } else {
            fprintf(stderr, "No changes detected in sensor data or LED state.\n");
        }

        // 更新上次的数据和LED状态
        last_sensor_data = current_sensor_data;
        last_led_state = led_state;
    }
}

void publish_partial_data_helper(const SensorData *data, bool led_state) {
    char payload[200];

    // 发布 LED 状态到 led002 主题
    snprintf(payload, sizeof(payload), "%s", led_state ? "on" : "off");
    int rc = mosquitto_publish(global_mosq, NULL, led_control_topic, strlen(payload), payload, 1, false);
    if (rc == MOSQ_ERR_SUCCESS) {
        printf("Published LED state to %s: %s\n", led_control_topic, payload);
    } else {
        fprintf(stderr, "Publish error (%s): %s\n", led_control_topic, mosquitto_strerror(rc));
    }

    // 发布温湿度数据和 LED 状态
    snprintf(payload, sizeof(payload), "#%.1f#%.1f#%s", data->temperature, data->humidity, led_state ? "on" : "off");
    rc = mosquitto_publish(global_mosq, NULL, dhttopic, strlen(payload), payload, 1, false);
    if (rc == MOSQ_ERR_SUCCESS) {
        printf("Published to %s: %s\n", dhttopic, payload);
    } else {
        fprintf(stderr, "Publish error (%s): %s\n", dhttopic, mosquitto_strerror(rc));
    }

    // 发布菜品信息
    rc = mosquitto_publish(global_mosq, NULL, dishes_topic, strlen(data->recommended_dish),
                          data->recommended_dish, 1, false);
    if (rc == MOSQ_ERR_SUCCESS) {
        printf("Published to %s: %s\n", dishes_topic, data->recommended_dish);
    } else {
        fprintf(stderr, "Publish error (%s): %s\n", dishes_topic, mosquitto_strerror(rc));
    }

    // 发布菜品状态（新鲜度）
    rc = mosquitto_publish(global_mosq, NULL, moldy_topic, strlen(data->freshness),
                          data->freshness, 1, false);
    if (rc == MOSQ_ERR_SUCCESS) {
        printf("Published to %s: %s\n", moldy_topic, data->freshness);
    } else {
        fprintf(stderr, "Publish error (%s): %s\n", moldy_topic, mosquitto_strerror(rc));
    }
}

void publish_full_data_helper(const SensorData *data, bool led_state) {
    publish_partial_data_helper(data, led_state);
}

// 初始化 MQTT 客户端
void init_mqtt_client() {
    if (!mqtt_initialized) {
        // 初始化Mosquitto库
        mosquitto_lib_init();

        // 创建一个新的Mosquitto客户端实例
        global_mosq = mosquitto_new(ID_MQTT, true, NULL);
        if (!global_mosq) {
            fprintf(stderr, "Error: Out of memory.\n");
            return;
        }

        // 设置回调函数，以便在特定事件发生时调用
        mosquitto_connect_callback_set(global_mosq, on_connect);
        mosquitto_publish_callback_set(global_mosq, on_publish);
        mosquitto_message_callback_set(global_mosq, on_message);
        mosquitto_subscribe_callback_set(global_mosq, on_subscribe);

        // 连接到指定的MQTT代理
        int rc = mosquitto_connect(global_mosq, mqtt_server, mqtt_server_port, 60);
        if (rc != MOSQ_ERR_SUCCESS) {
            fprintf(stderr, "Error connecting: %s\n", mosquitto_strerror(rc));
            mosquitto_destroy(global_mosq);
            mosquitto_lib_cleanup();
            return;
        }

        // 启动网络循环来处理网络通信
        rc = mosquitto_loop_start(global_mosq);
        if (rc != MOSQ_ERR_SUCCESS) {
            fprintf(stderr, "Error starting loop: %s\n", mosquitto_strerror(rc));
            mosquitto_destroy(global_mosq);
            mosquitto_lib_cleanup();
            return;
        }

        mqtt_initialized = true;
    }
}

// 清理 MQTT 客户端
void cleanup_mqtt_client() {
    if (mqtt_initialized) {
        // 停止网络循环
        mosquitto_loop_stop(global_mosq, true);
        mosquitto_destroy(global_mosq);
        mosquitto_lib_cleanup();
        mqtt_initialized = false;
    }
}

// 封装后的发布函数
void start_mqtt_publisher(int x, bool led_state) {
    // 初始化 MQTT 客户端
    init_mqtt_client();

    // 发布数据
    publish_partial_data(x, led_state);
}

// 接收服务器的LED状态并返回
bool mqtt_receive() {
    // 返回全局变量 led_state 的值
    return led_state;
}